﻿using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace RatingAuthor
{
  public sealed class MultithreadWorker<T> : BlockingCollection<T>
    where T : IWorkItem
  {
    private readonly Func<Task<T>> _startNewTask;
    private const int ThreadsCount = 1;
    private int _threadsCounter;
    private volatile Exception _error;

    public Exception Error
    {
      get { return _error; }
    }

    public MultithreadWorker(Func<Task<T>> startNewTask)
    {
      _startNewTask = startNewTask;
      _threadsCounter = ThreadsCount;
      for (int i = 0; i < ThreadsCount; i++)
        Worker();
    }

    private void Worker()
    {
      var task = _startNewTask();
      task.ContinueWith(t =>
        {
          if (task.Result.IsValid)
          {
            Add(task.Result);
            Worker();
          }
          else
          {
            _error = task.Exception;
            if (Interlocked.Decrement(ref _threadsCounter) == 0)
              CompleteAdding();
          }
        });
    }
  }
}